import { Component, OnInit, ViewChild } from '@angular/core';
import { IonContent, IonSlides, ModalController, PopoverController, ToastController } from '@ionic/angular';

import { forEach } from 'lodash';
import { asString } from 'date-format';
import * as clipboard from 'clipboard-polyfill/text';

import { pb } from 'src/pb';
import { sleep } from '../utils';
import { CallService } from '../call.service';
import { SettingsPage } from './settings/settings.page';
import { PopoverItem } from '../dialog/popover-options';
import { PopoverComponent } from '../dialog/popover/popover.component';

@Component({
  selector: 'app-random',
  templateUrl: './random.page.html',
  styleUrls: ['./random.page.scss'],
})
export class RandomPage implements OnInit {
  @ViewChild(IonContent, { static: true })
  content: IonContent;
  @ViewChild(IonSlides, { static: true })
  slides: IonSlides;
  game: any;
  games = [
    { code: 'coin', label: '抛硬币', icon: 'person-circle' },
    { code: 'three', label: '猜拳', icon: 'hand-right' },
    { code: 'dice', label: '掷骰子', icon: 'dice' },
    { code: 'group', label: '分组', icon: 'cellular' },
    { code: 'num', label: '随机数', icon: 'analytics-sharp' },
  ];
  result: pb.IRandomResult[][] = [];
  text = '';
  setting: pb.IRandomSettings = { time: true, min: 1, max: 100, num: 1, group: 4 };
  slideOpts = {
    allowTouchMove: false,
  };
  private index = 0;
  private groups: Array<number> = [];
  private coin = ['正面', '背面'];
  private colors = ['success', 'danger', 'warning', 'tertiary', 'medium', 'dark'];
  private coinIcons = ['person-circle', 'heart-circle'];
  private three = ['石头', '剪刀', '布　'];
  private threeIcons = ['thumbs-up-sharp', 'cut', 'hand-right'];
  constructor(
    private callService: CallService,
    private modalCtrl: ModalController,
    private toastCtrl: ToastController,
    private popoverCtrl: PopoverController,
  ) {

    this.game = this.games[0];
    for (const g of this.games) {
      this.result.push([]);
    }
  }

  select(i: number) {
    this.game = this.games[i];
    this.slides.slideTo(i);
    this.index = i;
    this.setText();
  }

  async play() {
    for (let i = 1; i <= this.setting.num; i++) {
      const r = new pb.RandomResult({
        time: asString('hh:mm:ss.SSS', new Date()),
        type: this.game.code,
        num: i,
      });
      switch (this.game.code) {
        case 'num':
          const n = this.random(this.setting.min, this.setting.max);
          r.label = `${n}`;
          r.value = n;
          break;
        case 'coin':
          const c = this.random(0, 1);
          r.label = this.coin[c];
          r.value = c;
          r.icon = this.coinIcons[c];
          r.color = this.colors[c];
          break;
        case 'three':
          const t = this.random(0, 2);
          r.label = this.three[t];
          r.value = t;
          r.icon = this.threeIcons[t];
          r.color = this.colors[t];
          break;
        case 'dice':
          const d = this.random(1, 6);
          r.label = `　${d}`;
          r.value = d;
          r.color = this.colors[(d + 1) % 6];
          r.icon = 'dice';
          break;
        case 'group':
          this.playGroup(r);
          break;
      }
      this.result[this.index].push(r);
    }

    this.setText();
    await sleep(100);
    this.content.scrollToBottom();
  }

  async openMenu(event: Event) {
    const items: PopoverItem[] = [
      { label: '复制结果', code: 'copy', icon: 'copy', iconColor: 'primary' },
      { label: '设置', code: 'settings', icon: 'settings', iconColor: 'success' },
      { label: '重新开始', code: 'cls', icon: 'trash', iconColor: 'danger' },
    ];
    const popover = await this.popoverCtrl.create({
      component: PopoverComponent,
      event,
      translucent: true,
      componentProps: {
        options: {
          title: '更多功能',
          items,
        }
      },
    });
    await popover.present();

    const r = await popover.onDidDismiss();

    if (r && r.data && this[r.data]) {
      this[r.data]();
    }
  }

  async copy() {
    await clipboard.writeText(this.text);
    const toast = await this.toastCtrl.create({
      message: `${this.games[this.index].label}结果已经复制`,
      duration: 2000,
      color: 'dark',
      position: 'top',
    });
    await toast.present();
  }

  async ngOnInit() {
    const setting = await this.callService.call('get',
      { def: this.setting, }, 'random');

    if (setting) {
      this.setting = setting;
    }
  }

  async settings() {
    const modal = await this.modalCtrl.create({
      component: SettingsPage,
      componentProps: { setting: Object.assign({}, this.setting) },
    });
    await modal.present();

    const r = await modal.onDidDismiss();
    if (r.data) {
      await this.callService.call('set', { msg: '保存设置' }, 'random', r.data);
      this.setting = r.data;
    }
  }

  async cls() {
    this.result[this.index] = [];
    this.setText();
    if (this.index === 3) {
      this.groups = [];
    }

    const toast = await this.toastCtrl.create({
      message: `${this.games[this.index].label}重新开始`,
      duration: 2000,
      color: 'dark',
      position: 'top',
    });
    await toast.present();
  }

  // 设置需要复制的文本
  private setText() {
    this.text = '';
    const group = new Map<number, Array<number>>();
    let sum = 0;

    forEach(this.result[this.index], (r, i) => {
      const num = this.setting.num === 1 ? i + 1 : r.num;
      if (r.type === 'group') {
        if (group.has(r.value)) {
          group.get(r.value).push(num);
        } else {
          group.set(r.value, [num]);
        }
      } else if (r.type === 'dice' && this.setting.num > 1) {
        sum += r.value;
        this.text += `${r.value} `;
        if (r.num === this.setting.num) {
          this.text += `= ${sum}\n`;
        } else {
          this.text += '+ ';
        }
      } else {
        this.text += `${num}: ${r.label.replace('　', '')}${this.setting.time ? ' ' + r.time : ''}\n`;
      }
    });

    if (group.size) {
      for (let i = 1; i <= this.setting.group; i++) {
        if (group.has(i)) {
          this.text += `组 ${i}: ${group.get(i).join(', ')}\n`;
        }
      }
    }
  }

  private playGroup(r: pb.IRandomResult) {
    // 初始化
    for (let i = 0; i < this.setting.group; i++) {
      if (!this.groups[i]) {
        this.groups[i] = 0;
      }
    }
    // 查找成员最少的组成员数量
    let min = Number.MAX_VALUE;
    for (const g of this.groups) {
      if (g < min) {
        min = g;
      }
    }
    // 查找最少成员的组
    const nums = [];
    this.groups.forEach((g, i) => {
      if (g === min) {
        nums.push(i + 1);
      }
    });

    let v = this.random(1, this.setting.group);
    if (nums.length > 0) {
      v = nums[this.random(0, nums.length - 1)];
    }

    this.groups[v - 1]++;
    r.label = `　组 ${v}`;
    r.value = v;
    r.color = this.colors[(v + 1) % 6];
    r.icon = 'cellular';
  }

  private random(min: number, max: number) {
    return Math.floor(Math.random() * (max - min + 1) + min);
  }
}

